/*
 * @(#)AssemblyDescriptorControllerMixin.java   09/10/11
 * 
 * Copyright (C) 2009 Ecole des Mines d'Ales
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: yulinz88@gmail.com
 */



package fr.ema.arch3d.ref.controllers.mixins;

import fr.ema.arch3d.model.architecture.configuration.Configuration;
import fr.ema.arch3d.model.architecture.configuration.ConnectorClass;
import fr.ema.arch3d.ref.Fractal;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalBindingException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.julia.Controller;
import org.objectweb.fractal.julia.InitializationContext;

import java.util.ArrayList;
import java.util.List;

//~--- classes ----------------------------------------------------------------

/**
 * Class description
 *
 *
 * @version        1.0, 09/09/13
 * @author         Huaxi (Yulin) ZHANG
 */
public abstract class AssemblyDescriptorControllerMixin
        implements fr.ema.arch3d.ref.controllers.interfaces.AssemblyDescriptorController, Controller {

    /** Field description */
    public List cmpIns_list, ctrIns_list, cmps_list, ctrs_list;

    /** Field description */
    private Component component_owner;

    /** Field description */
    public Configuration config;

    // content of component

    /** Field description */
    private Object fc_content;

    /** Field description */
    public String name;

    /** Field description */
    public String rules;

    /**
     * Method description
     *
     * @param ic  
     */
    public void initFcController(final InitializationContext ic) {
        try {
            this.component_owner = (Component) ic.getOptionalInterface("component");
            this.fc_content      = ic.content;
            this.cmpIns_list     = new ArrayList();
            this.ctrIns_list     = new ArrayList();
            this.cmps_list       = new ArrayList();
            this.ctrs_list       = new ArrayList();

            // call super controller
            _super_initFcController(ic);

            // if(this.fc_architecte)
            // call super method
            _super_initFcController(ic);
        } catch (Exception e) {
            System.out.println(e.toString());
            System.exit(-1);
        }
    }

    /**
     * Method description
     *
     * @param ic  
     */
    public abstract void _super_initFcController(InitializationContext ic);

    /**
     * Method description
     *
     * @param name  
     */
    public void setAssName(String name) {
        this.name = name;
    }

    /**
     * Method description
     *
     * @return  
     */
    public String getAssName() {
        return this.name;
    }

    /**
     * Method description
     *
     * @throws NoSuchInterfaceException  
     */
    public void getCurrentAssDescription() throws NoSuchInterfaceException {
        Component[] a = Fractal.getContentController(this.component_owner).getFcSubComponents();

        cmps_list.clear();
        ctrs_list.clear();

        for (int i = 0; i < a.length; i++) {
            if (Fractal.getElementtypeController(a[i]).getElementType().equals("component")) {
                String s2 = Fractal.getComponentDescriptorController(a[i]).getComponent().getName();
                String s1 = Fractal.getNameController(a[i]).getFcName();

                this.cmps_list.add(new String[] { s1, s2 });
            } else if (Fractal.getElementtypeController(a[i]).getElementType().equals("connector")) {
                String s2 = ((ConnectorClass) Fractal.getConnectorController(a[i]).getConnector()).getName();
                String s1 = Fractal.getNameController(a[i]).getFcName();

                this.ctrs_list.add(new String[] { s1, s2 });
            }
        }
    }

    /**
     * get the component instances and its correspondent components
     * @return list which contains String []:component instance name, component name
     */
    public List getCmpsList() {
        try {
            getCurrentAssDescription();
        } catch (NoSuchInterfaceException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return cmps_list;
    }

    /**
     * get the component instances and its correspondent components
     * @return
     */
    public List getCtrsList() {
        try {
            getCurrentAssDescription();
        } catch (NoSuchInterfaceException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return ctrs_list;
    }

    /**
     * set the configuration which this assembly instantiates
     * @param config  
     */
    public void setConfiguration(Configuration config) {
        this.config = config;
    }

    /**
     * get the configuration which this assembly instantiates
     * @return  
     */
    public Configuration getConfiguration() {
        return this.config;
    }

    /**
     * get component instances list which contained in this assembly
     * @return  
     */
    public List getCmpInsList() {
        Component[] a;

        try {
            a = Fractal.getContentController(this.component_owner).getFcSubComponents();

            for (int i = 0; i < a.length; i++) {
                if (Fractal.getElementtypeController(a[i]).getElementType().equals("component")) {
                    this.cmpIns_list.add(Fractal.getContentController(this.component_owner).getFcSubComponents()[i]);
                }
            }
        } catch (NoSuchInterfaceException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return this.cmpIns_list;
    }

    /**
     * get connectors instances list which contained in this assembly
     * @return  
     */
    public List getCtrInsList() {
        Component[] a;

        try {
            a = Fractal.getContentController(this.component_owner).getFcSubComponents();

            for (int i = 0; i < a.length; i++) {
                if (Fractal.getElementtypeController(a[i]).getElementType().equals("connector")) {
                    this.ctrIns_list.add(Fractal.getContentController(this.component_owner).getFcSubComponents()[i]);
                }
            }
        } catch (NoSuchInterfaceException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return this.ctrIns_list;
    }

    /**
     * Method description
     *
     * @param cmpL  
     */
    public void setCmpInsList(List cmpL) {
        this.cmpIns_list = cmpL;
    }

    /**
     * Method description
     *
     * @param ctrL  
     */
    public void setCtrInsList(List ctrL) {
        this.ctrIns_list = ctrL;
    }

    // public Vector config;

    /**
     * Method description
     *
     */
    public void bindContainer() {

        // binding
        try {
            System.out.println("bind");

            List        cmps = Fractal.getAssemblyDescriptorController(component_owner).getCmpInsList();
            List        ctrs = Fractal.getAssemblyDescriptorController(component_owner).getCtrInsList();
            Component[] a    = Fractal.getContentController(component_owner).getFcSubComponents();

            for (int i = 0; i < ctrs.size(); i++) {
                String cn = Fractal.getNameController((Component) ctrs.get(i)).getFcName();
                String cr = Fractal.getConnectorController(
                                (org.objectweb.fractal.api.Component) ((Component) ctrs.get(
                                    i))).getConnector().getClientCmpName();
                String crItf = Fractal.getConnectorController(
                                   (org.objectweb.fractal.api.Component) ((Component) ctrs.get(
                                       i))).getConnector().getClientItfName();
                String cp = Fractal.getConnectorController(
                                (org.objectweb.fractal.api.Component) ((Component) ctrs.get(
                                    i))).getConnector().getServerCmpName();
                String cpItf = Fractal.getConnectorController(
                                   (org.objectweb.fractal.api.Component) ((Component) ctrs.get(
                                       i))).getConnector().getServerItfName();
                int m = 0;

                for (int k = 0; k < a.length; k++) {
                    if (Fractal.getElementtypeController(a[k]).getElementType().equals("connector")) {
                        if (Fractal.getNameController(a[k]).getFcName().equals(cn)) {
                            m = k;
                        }
                    }
                }

                for (int j = 0; j < a.length; j++) {
                    if (Fractal.getElementtypeController(a[j]).getElementType().equals("component")) {
                        if (Fractal.getComponentDescriptorController(a[j]).getComponent().getName().equals(cr)) {
                            try {
                                Fractal.getBindingController(
                                    Fractal.getContentController(this.component_owner).getFcSubComponents()[j]).bindFc(
                                    crItf,
                                    (Fractal.getContentController(
                                        this.component_owner).getFcSubComponents()[m]).getFcInterface("p"));
                            } catch (IllegalBindingException e) {

                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (IllegalLifeCycleException e) {

                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }

                        if (Fractal.getComponentDescriptorController(a[j]).getComponent().getName().equals(cp)) {
                            try {
                                Fractal.getBindingController(
                                    Fractal.getContentController(this.component_owner).getFcSubComponents()[m]).bindFc(
                                    "r-I",
                                    (Fractal.getContentController(
                                        this.component_owner).getFcSubComponents()[j]).getFcInterface(cpItf));
                            } catch (IllegalBindingException e) {

                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (IllegalLifeCycleException e) {

                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        } catch (NoSuchInterfaceException e1) {

            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
}
